
#ifndef _Ship_H_
#define _Ship_H_

#include "Utils/Vector2D.h"
#include "WorldObject.h"
#include "Map.h"
#include "Weapons/Weapon.h"
#include "PowerUp/PowerUp.h"

#include <string>
#include <list>

class PowerUp;
class Player;
class Flag;
class Engine;
class Shield;

class Ship : public WorldObject {

  public:
    Ship(Player *controlling_player, Vector2D start_pos);
    ~Ship();

    void render(void);
    void renderMinimap(void);

    void update(void);
    bool active(void);

    bool resolveCollision(Ship *);
    bool resolveCollision(Weapon *);
    bool resolveCollision(Map *map);

    WorldObjectType getObjectType(void) const { return SHIP_WOBJECT; }

    // Control functions, the way in which an AI/Human 
    // player interacts with their ship.
    void accelerate(float how_much, bool afterburn);
    void side_thrust(float how_much);
    void post_accel(float how_much);
    void turn(float direction);
    void fire(bool primary = true);
    void switch_weapon(bool primary, bool forward);

    // Getter functions
    Vector2D getPosition(void) const;
    Vector2D getVelocity(void) const;
    Vector2D getCrosshairPos(void) const;
    Vector2D getHeading(void) const;
    float getRotation(void) const;
    float getSize(void) const;
    int getHealth(void) const;
    int getEnergy(void) const;
    Player* getControllingPlayer(void) const;

    // Setter functions
    void setPosition(Vector2D p);
    void setVelocity(Vector2D v);
    void setControllingPlayer(Player *controlling_player);

    void addPowerUp(PowerUp *power_up);

    void grabFlag(Flag *flag);
    bool resetHeldFlags(void); // TODO: change to drop flag
    bool haveFlag(void);

    // if amount is negative, then its equivalent to healing
    void dealDamage(int amount); 
    void impact(Vector2D rel_pos); 
    void die(void);

    // if amount is negative, same as restoring energy.
    void drainEnergy(float amount);

  private:
    
    std::string ship_type;
    unsigned ship_texture;

    Vector2D position; 
    Vector2D velocity;

    Player *controlling_player;

    float crosshair_dist;
    float targeting_rate;
    Vector2D crosshair_pos;

    Vector2D heading; // normalised alignment, derived from rotation
    float rotation;

    // Ship variables.
    float max_speed, acceleration;
    float turn_rate; // in degrees per second

    // world variables affecting the ship
    float drag_coeff; // how fast the ship decelerates under no thrust
    
    float size;
    float health, energy;
    bool is_active;
   
    std::list<PowerUp *> active_powerups;

    std::list<WeaponGenerator*> weapons_primary;
    std::list<WeaponGenerator*> weapons_secondary;
    WeaponGenerator *selected_weapon_primary, *selected_weapon_secondary;
    unsigned last_switch_time;


    Flag *held_flag;    
    Engine *engine;
    Shield *shield;

    friend class PowerUp;
    friend class SpeedPowerUp;
    friend class Engine;


    void purgeExpiredPowerUps(void);
    void renderCrosshair(void);
    
    void performCollisionTest(void);

};

#endif

